using System;
using System.Text;
using InfoJetSoft.Service.XPath;

//CID 0164 //2008.12.13 //Begin
namespace InfoJetSoft.Service.XPath.Exprs
{
	/// <summary>
	/// Summary description for PathExpr.
	/// </summary>
    public class PathExpr : IExpr
	{
        private IExpr _locationPath = null;

        private IExpr _filter = null;
        private OperatorExpr _separator = null;
        private IExpr _relative = null;

		public PathExpr()
		{
			//
			// TODO: Add constructor logic here
			//
        }

        public object Evaluate(ExprContext context)
        {
            //CID 0766 //2011.03.02 //Begin
            object result = null;
            context.Calculator.NewContext();
            if (this._locationPath != null)
            {
                //CID 0862 //Begin NodeTrace
                result = this._locationPath.Evaluate(context);
                //CID 0862 //End NodeTrace
            }
            else
            {
                //CID 0823 //2011.03.03 //Begin
                result = this._filter.Evaluate(context);
                if (this._separator != null)
                {
                    if (result is INodeList)
                    {
                        INodeList nodeList = (INodeList)result;
                        INodeList contextNodes = context.Calculator.CreateNodeList();
                        foreach (object node in nodeList)
                        {
                            contextNodes.Append(node);
                        }
                        if (this._separator.Operator == Operator.Slash)
                        {
                            context.Calculator.Slash(contextNodes);
                        }
                        else
                        {
                            context.Calculator.SlashSlash(contextNodes);
                        }
                        //CID 0862 //Begin NodeTrace
                        result = this._relative.Evaluate(context);
                        //CID 0862 //End NodeTrace
                    }
                    else
                    {
                        throw new ExprException("NodeList is expected.");
                    }
                }
                //CID 0823 //2011.03.03 //End
            }
            context.Calculator.DeleteContext();
            return result;
            //CID 0766 //2011.03.02 //End
        }

        //CID 0866 //2011.04.01 //Begin
        public void Visit(IExprVisitor visitor)
        {
            if (this._locationPath != null)
            {
                this._locationPath.Visit(visitor);
            }
            else
            {
                this._filter.Visit(visitor);
                if (this._separator != null)
                {
                    this._separator.Visit(visitor);
                    this._relative.Visit(visitor);
                }
            }
        }
        //CID 0866 //2011.04.01 //End

        public IExpr Path
        {
            get
            {
                return this._locationPath;
            }
        }

        public void Print(StringBuilder buffer)
        {
            if (this._locationPath != null)
            {
                this._locationPath.Print(buffer);
            }
            else
            {
                this._filter.Print(buffer);
                if (this._separator != null)
                {
                    this._separator.Print(buffer);
                    this._relative.Print(buffer);
                }
            }
        }

		public static IExpr Parse( ExprParser parser )
		{
			IExpr filterExpr = FilterExpr.Parse( parser );
			if( filterExpr != null )
			{
                OperatorExpr separator = OperatorExpr.ParseStepSeparator(parser);
				if( separator != null )
				{
					IExpr relativeLocationPath = RelativeLocationPath.Parse( parser );
					if( relativeLocationPath == null )
					{
						throw new Exception( "Cannot parse " + parser.XPath );
					}
					PathExpr pathExpr2 = new PathExpr();
					pathExpr2._filter = filterExpr;
					pathExpr2._separator = separator;
					pathExpr2._relative = relativeLocationPath;
					return pathExpr2;
				}

                return filterExpr;
            }

            IExpr locationPath = LocationPath.Parse(parser);
            if (locationPath != null)
            {
                PathExpr pathExpr = new PathExpr();
                pathExpr._locationPath = locationPath;
                return pathExpr;
            }
			
			return null;
		}
	}
}
//CID 0164 //2008.12.13 //End
